home *** CD-ROM | disk | FTP | other *** search
Perl POD Document | 1996-02-12 | 5.6 KB | 200 lines |
- package ExtUtils::Install;
-
- require Exporter;
- @ISA = ('Exporter');
- @EXPORT = ('install','uninstall');
-
- use Carp;
- use Cwd qw(cwd);
- use ExtUtils::MakeMaker; # to implement a MY class
- use File::Basename qw(dirname);
- use File::Copy qw(copy);
- use File::Find qw(find);
- use File::Path qw(mkpath);
- #use strict;
-
- sub install {
- my($hash,$verbose,$nonono) = @_;
- $verbose ||= 0;
- $nonono ||= 0;
- my(%hash) = %$hash;
- my(%pack, %write,$dir);
- local(*DIR, *P);
- for (qw/read write/) {
- $pack{$_}=$hash{$_};
- delete $hash{$_};
- }
- my($blibdir);
- foreach $blibdir (sort keys %hash) {
- #Check if there are files, and if yes, look if the corresponding
- #target directory is writable for us
- opendir DIR, $blibdir or next;
- while ($_ = readdir DIR) {
- next if $_ eq "." || $_ eq ".." || $_ eq ".exists";
- if (-w $hash{$blibdir} || mkpath($hash{$blibdir})) {
- last;
- } else {
- croak("You do not have permissions to install into $hash{$blibdir}");
- }
- }
- closedir DIR;
- }
- if (-f $pack{"read"}) {
- open P, $pack{"read"} or die "Couldn't read $pack{'read'}";
- # Remember what you found
- while (<P>) {
- chomp;
- $write{$_}++;
- }
- close P;
- }
- my $cwd = cwd();
- my $umask = umask 0;
-
- # This silly reference is just here to be able to call MY->catdir
- # without a warning (Waiting for a proper path/directory module,
- # Charles!) The catdir and catfile calls leave us with a lot of
- # paths containing ././, but I don't want to use regexes on paths
- # anymore to delete them :-)
- my $MY = {};
- bless $MY, 'MY';
- my($source);
- MOD_INSTALL: foreach $source (sort keys %hash) {
- #copy the tree to the target directory without altering
- #timestamp and permission and remember for the .packlist
- #file. The packlist file contains the absolute paths of the
- #install locations. AFS users may call this a bug. We'll have
- #to reconsider how to add the means to satisfy AFS users also.
- chdir($source) or next;
- find(sub {
- my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
- $atime,$mtime,$ctime,$blksize,$blocks) = stat;
- return unless -f _;
- return if $_ eq ".exists";
- my $targetdir = $MY->catdir($hash{$source},$File::Find::dir);
- my $targetfile = $MY->catfile($targetdir,$_);
- my $diff = 0;
-
- if ( -f $targetfile && -s _ == $size) {
- # We have a good chance, we can skip this one
- local(*F,*T);
- open F, $_ or croak("Couldn't open $_: $!");
- open T, $targetfile or croak("Couldn't open $targetfile: $!");
- my($fr, $tr, $fbuf,$tbuf,$size);
- $size = 1024;
- # print "Reading $_\n";
- while ( $fr = read(F,$fbuf,$size)) {
- unless (
- $tr = read(T,$tbuf,$size) and
- $tbuf eq $fbuf
- ){
- # print "diff ";
- $diff++;
- last;
- }
- # print "$fr/$tr ";
- }
- # print "\n";
- close F;
- close T;
- } else {
- print "$_ differs\n" if $verbose>1;
- $diff++;
- }
-
- if ($diff){
- mkpath($targetdir,0,0755) unless $nonono;
- print "mkpath($targetdir,0,0755)\n" if $verbose>1;
- unlink $targetfile if -f $targetfile;
- copy($_,$targetfile) unless $nonono;
- print "Installing $targetfile\n" if $verbose;
- utime($atime,$mtime,$targetfile) unless $nonono>1;
- print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
- chmod $mode, $targetfile;
- print "chmod($mode, $targetfile)\n" if $verbose>1;
- } else {
- print "Skipping $targetfile (unchanged)\n";
- }
-
- $write{$targetfile}++;
-
- }, ".");
- chdir($cwd) or croak("Couldn't chdir....");
- }
- umask $umask;
- if ($pack{'write'}) {
- $dir = dirname($pack{'write'});
- mkpath($dir,0,0755);
- print "Writing $pack{'write'}\n";
- open P, ">$pack{'write'}" or croak("Couldn't write $pack{'write'}: $!");
- for (sort keys %write) {
- print P "$_\n";
- }
- close P;
- }
- }
-
- sub uninstall {
- my($fil,$verbose,$nonono) = @_;
- die "no packlist file found: $fil" unless -f $fil;
- local *P;
- open P, $fil or croak("uninstall: Could not read packlist file $fil: $!");
- while (<P>) {
- chomp;
- print "unlink $_\n" if $verbose;
- unlink($_) || carp("Couldn't unlink $_") unless $nonono;
- }
- print "unlink $fil\n" if $verbose;
- unlink($fil) || carp("Couldn't unlink $fil") unless $nonono;
- }
-
- 1;
-
- __END__
-
- =head1 NAME
-
- ExtUtils::Install - install files from here to there
-
- =head1 SYNOPSIS
-
- B<use ExtUtils::Install;>
-
- B<install($hashref,$verbose,$nonono);>
-
- B<uninstall($packlistfile,$verbose,$nonono);>
-
- =head1 DESCRIPTION
-
- Both functions, install() and uninstall() are specific to the way
- ExtUtils::MakeMaker handles the installation and deinstallation of
- perl modules. They are not designed as general purpose tools.
-
- install() takes three arguments. A reference to a hash, a verbose
- switch and a don't-really-do-it switch. The hash ref contains a
- mapping of directories: each key/value pair is a combination of
- directories to be copied. Key is a directory to copy from, value is a
- directory to copy to. The whole tree below the "from" directory will
- be copied preserving timestamps and permissions.
-
- There are two keys with a special meaning in the hash: "read" and
- "write". After the copying is done, install will write the list of
- target files to the file named by $hashref->{write}. If there is
- another file named by $hashref->{read}, the contents of this file will
- be merged into the written file. The read and the written file may be
- identical, but on AFS it is quite likely, people are installing to a
- different directory than the one where the files later appear.
-
- uninstall() takes as first argument a file containing filenames to be
- unlinked. The second argument is a verbose switch, the third is a
- no-don't-really-do-it-now switch.
-
- =cut
-
- #=head1 NOTES
-
- #=head1 BUGS
-
- #=head1 AUTHORS
-
-